const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const compression = require('compression');
const rateLimit = require('express-rate-limit');
const { createServer } = require('http');
const { Server } = require('socket.io');
const path = require('path');
require('dotenv').config();

const { sequelize } = require('./utils/database');
const authRoutes = require('./routes/auth');
const activityRoutes = require('./routes/activities');
const feedRoutes = require('./routes/feeds');
const badgeRoutes = require('./routes/badges');
const userRoutes = require('./routes/users');
const adminRoutes = require('./routes/admin');
const { publicStatsRouter } = require('./routes/admin');

const app = express();
const server = createServer(app);
const io = new Server(server, {
  cors: {
    origin: process.env.FRONTEND_URL || "http://localhost:3000",
    methods: ["GET", "POST"]
  }
});

// 中间件配置
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'", "https://cdnjs.cloudflare.com"],
      scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "https://cdn.jsdelivr.net"],
      scriptSrcAttr: ["'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:", "http:", "blob:"],
      fontSrc: ["'self'", "https://cdnjs.cloudflare.com"],
      connectSrc: ["'self'", "ws:", "wss:"],
      objectSrc: ["'none'"],
      mediaSrc: ["'self'"],
      frameSrc: ["'none'"],
    },
  },
}));
app.use(compression());
app.use(morgan('combined'));
app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));

// 速率限制（测试环境下禁用）
if (process.env.NODE_ENV !== 'test') {
  const limiter = rateLimit({
    windowMs: 5 * 60 * 1000, // 5分钟
    max: 500, // 限制每个IP 5分钟内最多500个请求
    message: {
      error: '请求过于频繁，请稍后再试'
    },
    standardHeaders: true, // 在 `RateLimit-*` 头中返回速率限制信息
    legacyHeaders: false, // 禁用 `X-RateLimit-*` 头
  });
  app.use('/api/', limiter);
} else {
  console.log('测试环境：速率限制已禁用');
}

// 将 io 实例添加到 app 中，供路由使用
app.set('io', io);

// 根路径重定向到前端应用（必须在静态文件服务之前）
app.get('/', (req, res) => {
    res.redirect('/app.html');
});

// 静态文件服务
app.use('/uploads', express.static('uploads'));
app.use(express.static('public'));

// Socket.IO 连接处理
io.on('connection', (socket) => {
  console.log('用户连接:', socket.id);
  
  // 用户加入个人房间
  socket.on('join_user_room', (userId) => {
    socket.join(`user_${userId}`);
    console.log(`用户 ${userId} 加入房间`);
  });
  
  // 用户加入活动房间
  socket.on('join_activity_room', (activityId) => {
    socket.join(`activity_${activityId}`);
    console.log(`用户加入活动房间 ${activityId}`);
  });
  
  // 处理断开连接
  socket.on('disconnect', () => {
    console.log('用户断开连接:', socket.id);
  });
});

// API 路由
app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);
app.use('/api/activities', activityRoutes);
app.use('/api/badges', badgeRoutes);
app.use('/api/feeds', feedRoutes);
app.use('/api/admin', adminRoutes);
app.use('/api/stats', publicStatsRouter);

// 健康检查端点
app.get('/health', (req, res) => {
  res.json({
    status: 'OK',
    timestamp: new Date().toISOString(),
    uptime: process.uptime()
  });
});

// 404 处理 - 对于API路径返回JSON，对于其他路径返回HTML
app.use('*', (req, res) => {
  if (req.originalUrl.startsWith('/api/')) {
    res.status(404).json({
      error: '接口不存在',
      path: req.originalUrl
    });
  } else {
    res.status(404).sendFile(path.join(__dirname, 'public', 'index.html'));
  }
});

// 全局错误处理
app.use((err, req, res, next) => {
  console.error('错误:', err);
  
  if (err.name === 'ValidationError') {
    return res.status(400).json({
      error: '数据验证失败',
      details: err.message
    });
  }
  
  if (err.name === 'JsonWebTokenError') {
    return res.status(401).json({
      error: '无效的访问令牌'
    });
  }
  
  res.status(500).json({
    error: '服务器内部错误',
    message: process.env.NODE_ENV === 'development' ? err.message : '请稍后重试'
  });
});

// 数据库连接和服务器启动
const PORT = process.env.PORT || 3000;

async function startServer() {
  try {
    // 测试数据库连接
    await sequelize.authenticate();
    console.log('数据库连接成功');
    
    // 同步数据库模型
    if (process.env.NODE_ENV === 'development') {
      // 暂时禁用自动同步，避免索引冲突
      // await sequelize.sync({ alter: true });
      console.log('数据库模型同步已跳过');
    }
    
    // 启动服务器
    server.listen(PORT, () => {
      console.log(`服务器运行在端口 ${PORT}`);
      console.log(`环境: ${process.env.NODE_ENV}`);
    });
  } catch (error) {
    console.error('服务器启动失败:', error);
    process.exit(1);
  }
}

startServer();

module.exports = app; 